package com.lib.utils;

import static android.content.Context.CLIPBOARD_SERVICE;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;

import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.text.TextUtils;
import android.view.accessibility.AccessibilityNodeInfo;

import java.util.ArrayList;
import java.util.List;

/**
 * @author 一叶丶枫凌
 * 描述：
 * Created on 2018-09-27 下午 06:49
 */
public class AccessWebUtil {
    public static boolean canPerformAuto(Context context, String name) {
        String services = null;
        try {
            services = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
        } catch (Exception ignored) {
        }
        return services != null && services.toLowerCase().contains(name.toLowerCase());
    }

    public static void openSettings(Context context) {
        XLog.i("to open accessibility settings");
        Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);
    }

    /**
     * 遍历传入节点下的所有节点信息，
     *
     * @param deep     当前层级深度
     * @param nodeInfo 需要展示子节点信息的节点
     */
    public static void showAllNodeInfoText(int deep, AccessibilityNodeInfo nodeInfo, boolean showContentDesc) {
        if (nodeInfo == null) {
            XLog.i("nodeInfo == null");
            return;
        }
        int childCount = nodeInfo.getChildCount();
        if (childCount > 0) {
            XLog.i(String.format("容器--》节点信息--》 %d、%d-->%s-->%s-->\n\n",
                    deep, childCount, nodeInfo.getClassName(), nodeInfo.getText()));
            for (int i = 0; i < childCount; i++) {
                showAllNodeInfoText(i, nodeInfo.getChild(i), showContentDesc);
            }
        } else {
            CharSequence contentDescription = nodeInfo.getContentDescription();
            XLog.i(String.format("子控件--》节点信息--》 %d、%s-->%s-->%s\n\n",
                    deep, nodeInfo.getClassName(), nodeInfo.getText(), showContentDesc ? contentDescription : ""));
        }
    }

    /**
     * 遍历传入节点下的所有节点信息，
     *
     * @param nodeInfo   需要展示子节点信息的节点
     * @param sb         若不为空，则会添加上每个View节点的描述文本
     * @param isNeedDesc
     */
    public static void getAllNodeTextAndDescription(AccessibilityNodeInfo nodeInfo, StringBuilder sb, boolean isNeedDesc) {
        if (nodeInfo == null) {
            XLog.i(" null 节点");
            return;
        }
        int childCount = nodeInfo.getChildCount();
        if (childCount > 0) {
            for (int i = 0; i < childCount; i++) {
                getAllNodeTextAndDescription(nodeInfo.getChild(i), sb, isNeedDesc);
            }
        } else {
            if (sb != null) {
                CharSequence text = nodeInfo.getText();
                if (text != null) {
                    sb.append(text).append("_");
                }
                if (isNeedDesc) {
                    CharSequence contentDescription = nodeInfo.getContentDescription();
                    if (contentDescription != null) {
                        sb.append(contentDescription).append("_");
                    }
                }
            }
        }
    }

    /**
     * 遍历传入节点下的所有节点信息，
     *
     * @param nodeInfo 需要展示子节点信息的节点
     * @param sb       若不为空，则会添加上每个View节点的描述文本
     */
    public static void getAllNodeTextInfo(AccessibilityNodeInfo nodeInfo, StringBuilder sb) {
        if (nodeInfo == null) {
            XLog.i(" null 节点");
            return;
        }
        int childCount = nodeInfo.getChildCount();
        if (childCount > 0) {
            for (int i = 0; i < childCount; i++) {
                getAllNodeTextInfo(nodeInfo.getChild(i), sb);
            }
        } else {
            if (sb != null) {
                CharSequence text = nodeInfo.getText();
                if (text != null) {
                    sb.append(text).append("_0=0_");
                }
            }
        }
    }

    /**
     * 遍历节点下的所有节点，如果为text不空，则返回对应的节点对象
     *
     * @param nodeInfo 需要遍历的节点
     * @param text     需要返回的节点text值
     * @return 找到的节点
     */
    public static AccessibilityNodeInfo findFirstNodeWithTextOrId(AccessibilityNodeInfo nodeInfo, String text) {
        if (text == null) {
            XLog.i("text is null");
            return null;
        }
        if (nodeInfo == null) {
            XLog.i("nodeInfo is null");
            return null;
        }
        int childCount = nodeInfo.getChildCount();
        if (childCount == 0) {
            CharSequence rawText = nodeInfo.getText();
            String resId = nodeInfo.getViewIdResourceName();
            // XLog.i( "文本-》" + rawText + " id--》" + resId);
            if ((text.contentEquals(rawText)) || (text.equals(resId))) {
                return nodeInfo;
            }
        }
        for (int i = 0; i < childCount; i++) {
            AccessibilityNodeInfo nd = findFirstNodeWithTextOrId(nodeInfo.getChild(i), text);
            if (nd != null) {
                return nd;
            }
        }
        return null;
    }

    public static void findNodesWithTextOrId(AccessibilityNodeInfo nodeInfo, String text, ArrayList<AccessibilityNodeInfo> list) {
        if (text == null) {
            XLog.i("text is null");
            return;
        }
        if (nodeInfo == null) {
            XLog.i("nodeInfo is null");
            return;
        }
        int childCount = nodeInfo.getChildCount();
        if (childCount == 0) {
            CharSequence rawText = nodeInfo.getText();
            String resId = nodeInfo.getViewIdResourceName();
            // XLog.i( "文本-》" + rawText + " id--》" + resId);
            if ((text.contentEquals(rawText)) || (text.equals(resId))) {
                list.add(nodeInfo);
            }
        }
        for (int i = 0; i < childCount; i++) {
            findNodesWithTextOrId(nodeInfo.getChild(i), text, list);
        }
    }

    /**
     * 遍历节点下的所有节点，找到WebView的节点对象
     *
     * @param nodeInfo 需要遍历的节点
     * @param clzName  控件类
     * @return 找到的WebView节点
     */
    public static AccessibilityNodeInfo findNodeByClassName(AccessibilityNodeInfo nodeInfo, String clzName) {
        if (clzName == null) {
            XLog.i("clzName is null");
            return null;
        }
        if (nodeInfo == null) {
            XLog.i("nodeInfo is null");
            return null;
        }
        int childCount = nodeInfo.getChildCount();
        for (int i = 0; i < childCount; i++) {
            CharSequence className = nodeInfo.getClassName();
            if (clzName.contentEquals(className)) {
                // XLog.i( "className:" + className);
                return nodeInfo;
            }
            AccessibilityNodeInfo nd = findNodeByClassName(nodeInfo.getChild(i), clzName);
            if (nd != null) {
                return nd;
            }
        }
        return null;
    }

    /**
     * 找到WebView下的指定节点信息
     *
     * @param nodeInfo 为提高效率，建议是WebView的节点
     */
    public static AccessibilityNodeInfo findNodeFromWebViewWithText(int deep, AccessibilityNodeInfo nodeInfo, String text) {
        if (nodeInfo == null) {
            XLog.i(deep + ".nodeInfo is null");
            return null;
        }
        int childCount = nodeInfo.getChildCount();
        if (childCount == 0) {
            CharSequence contentDescription = nodeInfo.getContentDescription();
            if (contentDescription != null && contentDescription.toString().equals(text)) {
                // XLog.i( "搜索到 " + deep + "-->" + contentDescription);
                if ("更多".equals(text)) {
                    if (nodeInfo.getViewIdResourceName() == null) {
                        return nodeInfo;
                    }
                } else {
                    return nodeInfo;
                }
            }
        }
        for (int i = 0; i < childCount; i++) {
            AccessibilityNodeInfo info = findNodeFromWebViewWithText(i, nodeInfo.getChild(i), text);
            if (info != null) {
                return info;
            }
        }
        return null;
    }

    public static boolean setTextToNode(Context context, AccessibilityNodeInfo nodeInfo, String text, boolean append) {
        if (nodeInfo == null) {
            XLog.i("nodeInfo is null");
            return false;
        }
        if (append) {
            CharSequence oldText = nodeInfo.getText();
            if (!TextUtils.isEmpty(oldText)) {
                text = oldText + text;
            }
        }
        if (Build.VERSION.SDK_INT > 20) {
            Bundle arguments = new Bundle();
            arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text);
            return nodeInfo.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
        } else {
            ClipboardUtils.copyText(context, text);
            return nodeInfo.performAction(AccessibilityNodeInfo.ACTION_PASTE);
        }
    }

    public static boolean setNodeTextBackspace(Context context, AccessibilityNodeInfo nodeInfo) {
        if (nodeInfo == null) {
            XLog.i("nodeInfo is null");
            return false;
        }
        CharSequence oldText = nodeInfo.getText();
        if (!TextUtils.isEmpty(oldText)) {
            oldText = oldText.subSequence(0, oldText.length() - 1);
        }
        if (Build.VERSION.SDK_INT > 20) {
            Bundle arguments = new Bundle();
            arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, oldText);
            return nodeInfo.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
        } else {
            ClipboardUtils.copyText(context, oldText);
            return nodeInfo.performAction(AccessibilityNodeInfo.ACTION_PASTE);
        }
    }

    /**
     * 通过名字获取控件，并进行模拟点击
     *
     * @param nodeInfo 节点
     * @param resId    指定控件的文本
     * @return 点击成功返回true
     */
    public static AccessibilityNodeInfo findNodeByResId(AccessibilityNodeInfo nodeInfo, String resId) {
        return findNodeByResId(nodeInfo, resId, 0);
    }

    public static AccessibilityNodeInfo findNodeByResId(AccessibilityNodeInfo nodeInfo, String resId, int index) {
        if (nodeInfo == null) {
            XLog.i("nodeInfo is null");
            return null;
        }
        List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByViewId(resId);
        if (list != null) {
            int size = list.size();
            if (size != 0 && index < size) {
                return list.get(index);
            }
        }
        return null;
    }

    public static AccessibilityNodeInfo findNodeByText(AccessibilityNodeInfo nodeInfo, String btnName) {
        return findNodeByText(nodeInfo, btnName, 0);
    }

    public static AccessibilityNodeInfo findNodeByText(AccessibilityNodeInfo nodeInfo, String btnName, int index) {
        if (nodeInfo == null) {
            XLog.i("nodeInfo is null");
            return null;
        }
        List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByText(btnName);
        if (list != null) {
            int size = list.size();
            if (size != 0 && index < size) {
                return list.get(index);
            }
        }
        return null;
    }

    public static boolean clickNodeToParent(AccessibilityNodeInfo nodeInfo) {
        if (nodeInfo == null) {
            XLog.i("nodeInfo is null");
            return false;
        }
        if (nodeInfo.isClickable()) {
            // XLog.i(TAG + "qwq", nodeInfo.getClassName() + "---------> 可点击");
            nodeInfo.performAction(ACTION_CLICK);
            return true;
        }
        return clickNodeToParent(nodeInfo.getParent());
    }

    public static boolean clickNodeInfoToChild(AccessibilityNodeInfo nodeInfo) {
        if (nodeInfo == null) {
            XLog.i("nodeInfo is null");
            return false;
        }
        if (nodeInfo.isClickable()) {
            // XLog.i(TAG + "qwq", nodeInfo.getClassName() + "---------> 可点击");
            nodeInfo.performAction(ACTION_CLICK);
            return true;
        }
        AccessibilityNodeInfo child = nodeInfo.getChild(0);
        return clickNodeInfoToChild(child);
    }
}